package com.linsen.erp.admin.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.linsen.core.common.context.TokenContextHolder;
import com.linsen.core.common.model.User;
import com.linsen.core.common.util.ConvertUtil;
import com.linsen.core.log.enums.LoginType;
import com.linsen.core.log.model.Log;
import com.linsen.core.redis.util.RedisSecurityUtil;
import com.linsen.erp.admin.entity.LoginLogEntity;
import com.linsen.erp.admin.mapper.LoginLogMapper;
import com.linsen.erp.admin.provider.qo.LoginLogQo;
import com.linsen.erp.admin.provider.vo.AnalyseVO;
import com.linsen.erp.admin.provider.vo.LoginLogVO;
import com.linsen.erp.admin.service.ILoginLogService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 登录日志 服务实现类
 * </p>
 *
 * @author zhaoyong
 * @since 2023-07-24
 */
@Service
@RequiredArgsConstructor
public class LoginLogServiceImpl extends ServiceImpl<LoginLogMapper, LoginLogEntity> implements ILoginLogService {
    private final RedisSecurityUtil redisSecurityUtil;

    /** 封装分页列表查询的wrapper对象 */
    private Wrapper<LoginLogEntity> getWrapper(LoginLogQo loginLogQo){
        Integer type = loginLogQo.getType();
        String ip = loginLogQo.getIp();
        String createByName = loginLogQo.getCreateByName();
        LocalDateTime startTime = loginLogQo.getStartTime();
        LocalDateTime endTime = loginLogQo.getEndTime();

        return new LambdaQueryWrapper<LoginLogEntity>()
                .eq(ObjectUtil.isNotNull(type),LoginLogEntity::getType,type)
                .like(ObjectUtil.isNotEmpty(ip),LoginLogEntity::getIp,ip)
                .like(ObjectUtil.isNotEmpty(createByName),LoginLogEntity::getCreateByName,createByName)
                .ge(ObjectUtil.isNotNull(startTime),LoginLogEntity::getCreateTime, startTime)
                .le(ObjectUtil.isNotNull(endTime),LoginLogEntity::getCreateTime, endTime)
                .orderByDesc(LoginLogEntity::getCreateTime);
    }

    @Override
    public Page<LoginLogEntity> page(LoginLogQo qo) {
        return this.page(new Page<>(qo.getCurrent(), qo.getSize()), getWrapper(qo));
    }

    @Override
    public LoginLogVO last() {
        User user = this.redisSecurityUtil.getUser(TokenContextHolder.getToken());
        String userid = user.getUserid();

        List<LoginLogEntity> loginLogEntityList = this.list(
                new LambdaQueryWrapper<LoginLogEntity>()
                        .eq(LoginLogEntity::getCreateBy, userid)
                        .eq(LoginLogEntity::getType, LoginType.LOGININ.getValue())
                        .orderByDesc(LoginLogEntity::getCreateTime)
        );
        if(ObjectUtil.isEmpty(loginLogEntityList)){
            return null;
        }

        return ConvertUtil.convert(loginLogEntityList.get(0),LoginLogVO.class);
    }

    @Override
    public AnalyseVO analyse() {
        LocalDate today = LocalDate.now();
        LocalDate firstDay = today.minusDays(29);

        LocalDateTime beginTime = LocalDateTime.of(firstDay, LocalTime.MIN);
        LocalDateTime endTime = beginTime.plusDays(30L);

        Map<LocalDate,Integer> logininMap = new HashMap<>();
        this.list(
                new LambdaQueryWrapper<LoginLogEntity>()
                        .eq(LoginLogEntity::getType, LoginType.LOGININ.getValue())
                        .ge(LoginLogEntity::getCreateTime,beginTime)
                        .lt(LoginLogEntity::getCreateTime,endTime)
        ).forEach(loginLogEntity -> {
            LocalDate currentDay = loginLogEntity.getCreateTime().toLocalDate();
            Integer count = logininMap.getOrDefault(currentDay, 0);
            logininMap.put(currentDay,count+1);
        });

        AnalyseVO analyseVO = new AnalyseVO();
        List<AnalyseVO.DataInfo> dataInfoList = new ArrayList<>();

        LocalDate currentDay = firstDay;
        while (!currentDay.isAfter(today)){
            int monthValue = currentDay.getMonthValue();
            int dayOfMonth = currentDay.getDayOfMonth();

            AnalyseVO.DataInfo dataInfo = new AnalyseVO.DataInfo();
            dataInfo.setXAxis(monthValue + "." + dayOfMonth);
            dataInfo.setYAxis(logininMap.getOrDefault(currentDay,0));
            dataInfoList.add(dataInfo);

            currentDay = currentDay.plusDays(1L);
        }
        analyseVO.setDataInfoList(dataInfoList);

        return analyseVO;
    }
}
